using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Playables;

//这里让我认识到不同开发环境下Edior/PlayMode/不同平台下
//用不同的接口+宏重载实现方式有多么重要

#if UNITY_EDITOR && DEBUG
[ExecuteAlways]
#endif
public class ObserverSystem : MonoBehaviour
{
    public void InitObserverSystem()
    {
        serverPool = new();
        chainPool = new();
        instance = this;
    }
    //由于不希望每帧都进行类型装换

    private void OnDestroy()
    {
        foreach (var ob in serverPool)
        {
            ob.SelfCancle();
        }
        serverPool.Clear();
    }

    //TODO: 拿tickType分池
    public static List<Observer> serverPool;
    public static List<ObserverChain> chainPool;
    public static ObserverSystem instance;

    public static Observer Add(Observer observer)
    {
        serverPool.Add(observer);
        return observer;
    }
    public static void Cancle(Observer observer)
    {
        //TODO:取消目标observer
        observer.valid = false;
    }
    public static Observer AddUnique(Observer observer)
    {
        observer.Reset();
        if (!serverPool.Contains(observer))
            serverPool.Add(observer);
        return observer;
    }
    public static void RegisteChain(ObserverChain chain)
    {
        var exist = chainPool.Find(x => x == chain);
        if (exist == null)
        {
            chainPool.Add(chain);
        }
    }
    private void Update()
    {
        if (serverPool == null) return;
        for (int i = 0; i < serverPool.Count; i++)
        {
            Observer item = serverPool[i];
            if (item == null || !item.valid || item.tickType != 1) continue;

            if (!item.Complete())
            {
                item.Tick();
            }
            else if (item.loopCount != 0)
            {
                item.Reset();
                --item.loopCount;
                item.end?.Invoke();
                item.TailRelatedInvoke();
            }
            else
            {
                item.end?.Invoke();
                item.valid = false;
                item.TailRelatedInvoke();
            }
        }
    }

    private void FixedUpdate()
    {
        if (serverPool == null) return;
        //这部分考虑Try Catch块,否则end报错之后item.valid无法修改, 不过直接放在最后就行了
        for (int i = 0; i < serverPool.Count; i++)
        {
            Observer item = serverPool[i];
            if (item == null || !item.valid || item.tickType != 0) continue;
            bool c = item.Complete();
            if (!c)
            {
                item.Tick();
            }
            else if (item.loopCount != 0)
            {
                item.Reset();
                --item.loopCount;
                item.end?.Invoke();
                item.TailRelatedInvoke();
            }
            else
            {
                item.valid = false;
                item.end?.Invoke();
                item.TailRelatedInvoke();

            }
        }

    }


}
public abstract class Observer
{
    public string name;
    public bool valid = true;
    public int tickType = 0;
    public int loopCount = 0;//0表示不循环(1) 1表示循环一次(2)
    public ObserverChain onChain;
    public object relatedResource;
    public abstract ObserverType type { get; }
    public Action start;
    public Action tick;
    public Action end;

    public abstract Observer Clone();
    public abstract bool Complete();
    public virtual void Tick() { tick?.Invoke(); }
    public void SelfCancle() => valid = false;

    /// <summary>
    /// 数据驱动的Observer , 数据要重置 , LoopCount没有重置
    /// </summary>
    public virtual void Reset()
    {
        valid = true;
    }

    #region Head&Tail link
    public List<Observer> headRelated;
    public List<Observer> tailRelated;

    public void AddHead(Observer observer)
    {
        if (headRelated != null) headRelated.Add(observer);
        else headRelated = new List<Observer>() { observer };
    }
    public void AddTail(Observer observer)
    {
        if (tailRelated != null) tailRelated.Add(observer);
        else tailRelated = new List<Observer>() { observer };
    }


    public void HeadRelatedInvoke()
    {
        if (headRelated != null)
        {
            foreach (var ob in headRelated)
            {
                onChain?.Add(ob);
                ob.Subscribe();
            }
        }
    }
    public void TailRelatedInvoke()
    {
        if (tailRelated != null)
            foreach (var ob in tailRelated)
            {
                onChain?.Add(ob);
                ob.Subscribe();
            }
    }

    public bool IsHeadOnChain()
    {
        //认为没有chain也是head
        return onChain == null || onChain.head == this;
        //克隆的时候这里的头锁的还是旧的, 这就牵扯到链上的observer是否唯一了,目前是唯一
        //或者说链的头一定是唯一的
    }
    public void DismissChain()
    {
        if (onChain == null) return;
        onChain.live = false;
        foreach (var observer in onChain.sets)
        {
            observer.SelfCancle();
        }
        Dispose();
        this.SelfCancle();
    }

    public void InvokeChain()
    {
        if (onChain != null)
            onChain.live = true;
    }

    public void Dispose()
    {
        foreach (var ob in onChain.relays)
        {
            ob.SelfCancle();
        }
        onChain.relays.Clear();
    }

    #endregion
}
public enum ObserverType
{
    Base = 0,
    Trigger = 1,
    Timer = 2,
    Func = 3,
    Flow = 4
}

public class TObserver : Observer
{
    //是多少就是多少, 时间是绝对的
    public override ObserverType type => ObserverType.Timer;
    public float startTime;
    public float duration;
    public float ToLinerLerp => (Time.time - startTime) / duration;
    public TObserver()
    {
        startTime = Time.time;
    }

    public override bool Complete()
    {
        return (Time.time - startTime) >= duration;
    }
    public override void Reset()
    {
        base.Reset();
        startTime = Time.time;
    }

    public override Observer Clone()
    {
        TObserver o = new();
        o.name = name;
        o.tickType = tickType;
        o.loopCount = loopCount;
        o.onChain = onChain;
        o.start = start;
        o.tick = tick;
        o.end = end;
        o.headRelated = headRelated;
        o.tailRelated = tailRelated;

        o.startTime = Time.time;
        o.duration = duration;
        o.relatedResource = relatedResource;
        return o;
    }
}
public class FuncObserver : Observer
{
    //条件一旦触发, 是没有容忍度的
    public override ObserverType type => ObserverType.Func;

    public Func<bool> complete;
    public void SetComplete() =>
    completeFlag = true;
    private bool completeFlag; // 加一个记录位捕获触发条件的瞬间
    public override bool Complete()
    {
        if (complete != null)
            completeFlag |= complete();
        return completeFlag;
    }
    public override Observer Clone()
    {
        FuncObserver o = new();
        o.name = name;
        o.tickType = tickType;
        o.loopCount = loopCount;
        o.onChain = onChain;
        o.start = start;
        o.tick = tick;
        o.end = end;
        o.headRelated = headRelated;
        o.tailRelated = tailRelated;

        o.complete = complete;
        o.relatedResource = relatedResource;
        return o;
    }
}
public class FlowObserver : Observer
{
    //实际上当StartFrame =0 ,inflow = true 时, FlowObserver退化为FuncObserver , 但是Func能在渲染帧中跑, 两者因为这一点差别而必须存在
    //最稳妥的方案就是按照tick帧来写 , 这个只接受fixedUpdate , 一帧 0.02s

    //2025年3月20日 20:04:48更新
    //流服务应该手动开关 , 设置autoDestory服务, 为0时候也存活,但是不提供tick服务
    public override ObserverType type => ObserverType.Func;
    public int startFrame = 0; //默认是2
    const int frameAdd = 1;
    const int frameMinus = 1;
    public int flowFrame = 0;
    public Func<bool> flowin;

    public FlowObserver()
    {

    }
    /// <summary>
    /// 问题就在这个inflow是如何调用的 , 交由外部保管还是一个 func 来调用
    /// </summary>
    public void Inflow()
    {
        //这个地方为了保证0状态时候能+2-1实现缓存避免直接触发end
        if (flowFrame == 0) flowFrame += frameAdd;
        flowFrame += frameAdd;
    }
    public void Outflow()
    {
        flowFrame -= frameMinus;
    }
    public void ShutDown()
    {
        flowFrame = 0;
    }
    public bool autoClose = false;
    public bool complete => flowFrame <= 0;

    public override bool Complete()
    {
        if (autoClose) return complete;
        else return false;
    }
    public override void Tick()
    {
        if (flowin.Invoke()) Inflow();

        if (flowFrame == 0) return;
        tick?.Invoke();
        Outflow();
        if (flowFrame == 0) end?.Invoke();
    }
    public override void Reset()
    {
        base.Reset();
        flowFrame = 0;
    }

    public override Observer Clone()
    {
        FlowObserver o = new();
        o.name = name;
        o.tickType = tickType;
        o.loopCount = loopCount;
        o.onChain = onChain;
        o.start = start;
        o.tick = tick;
        o.end = end;
        o.headRelated = headRelated;
        o.tailRelated = tailRelated;

        o.startFrame = startFrame;
        o.flowin = flowin;
        o.autoClose = autoClose;
        return o;
    }
}
public class TriggerObserver : Observer
{
    public override ObserverType type => ObserverType.Trigger;

    public override bool Complete()
    {
        return true;
    }

    public override Observer Clone()
    {
        TriggerObserver o = new();
        o.name = name;
        o.tickType = tickType;
        o.loopCount = loopCount;
        o.onChain = onChain;
        o.start = start;
        o.tick = tick;
        o.end = end;
        o.headRelated = headRelated;
        o.tailRelated = tailRelated;

        o.relatedResource = relatedResource;
        return o;
    }
}

public class ObserverChain
{
    //思考什么是链, 链上是否有次序性, 先做简单的全面破坏性, 

    //并查集式的链,其实更准确地叫区块
    //链本身有状态, 链持有在系统上, 服务注册到系统的时候才能知道链是否失活

    public Observer head;
    public bool live = true;
    public ObserverChain(Observer head)
    {
        head.onChain = this;
        this.head = head;
        sets = new HashSet<Observer>() { head };
        relays = new();
    }
    public HashSet<Observer> sets;
    public HashSet<Observer> relays;
    public void Add(Observer observer)
    {
        observer.onChain = this;
        sets.Add(observer);
    }
}

public static class ObserverExtension
{
    //也就是说链条调用是需要考虑传递性的, return back 是传递到下一个, return front是维持原生性质
    public static Observer Subscribe(this Observer observer, bool sonClassCall = false)
    {
        //操了这部分逻辑还是不对  FIX: 头尾关联ob没clone进去
        Observer existObserver = ObserverSystem.AddUnique(observer);
        // if (observer.unique)
        //     existObserver = ObserverSystem.AddUnique(observer);
        // else
        //     existObserver = ObserverSystem.Add(observer.Clone());
        //如果这里的Observer有chain的话,尝试注册在链上
        //其实这个地方就要判断chain的活性了

        if (existObserver.IsHeadOnChain())
        {
            ObserverSystem.RegisteChain(existObserver.onChain);
            existObserver.InvokeChain();
        }
        else if (!existObserver.onChain.live)
        {
            //这里判断是否失活 , 失活则不处理
            existObserver.SelfCancle();
            return existObserver;
        }

        existObserver.start?.Invoke();
        existObserver.HeadRelatedInvoke();
        return existObserver;
        //目前这里是根据object hash来判断是否相同的 , 可能考虑Name unique
    }
    public static Observer Cancel(this Observer observer)
    {
        ObserverSystem.Cancle(observer);
        return observer;
    }

    public static Observer Link(this Observer frontObserver, Observer backwardObserver)
    {
        frontObserver.AddTail(backwardObserver);
        return frontObserver;
    }
    public static Observer Next(this Observer frontObserver, Observer backwardObserver)
    {
        frontObserver.AddTail(backwardObserver);
        return backwardObserver;
    }

    public static Observer NextNew(this Observer frontObserver, Func<Observer> fnew)
    {
        frontObserver.end += () => fnew().Subscribe();
        return frontObserver;
    }

    /// <summary>
    /// Wait的起点是后置的, 前面并驾齐驱等待后方 , 因为frontObserver无法同时等待两个条件
    /// </summary>
    /// <param name="frontObserver"></param>
    /// <param name="backwardObserver"></param>
    /// <returns></returns>
    public static Observer Wait(this Observer frontObserver, Observer backwardObserver)
    {
        backwardObserver.AddHead(frontObserver);
        return backwardObserver;
    }
    public static ObserverChain BuildChain(this Observer frontObserverr)
    {
        //链头标识是唯一的
        ObserverChain chain = new(frontObserverr);
        return chain;
    }
    public static ObserverChain Subscribe(this ObserverChain chain)
    {
        chain.head.Subscribe();
        return chain;
    }
    #region  TypeOverride
    public static TObserver Subscribe(this TObserver observer)
    {
        observer.Subscribe(true);
        return observer;
    }
    public static FuncObserver Subscribe(this FuncObserver observer)
    {
        observer.Subscribe(true);
        return observer;
    }
    public static bool Validate(this Observer observer)
    {
        return observer != null && observer.valid;
    }
    #endregion

    public static TObserver Delay(this float t, Action action)
    {
        return new TObserver()
        {
            duration = t,
            end = action
        }.Subscribe();
    }
    public static TObserver CreateDelay(this float t, Action action = null)
    {
        return new TObserver()
        {
            duration = t,
            end = action
        };
    }


    public static void RelayOn(this Observer observer, Observer head)
    {
        head.onChain.relays.Add(observer);
    }

}

public static class MultifunctionalObserverExtension
{
    public static TObserver uniLogger = new TObserver();
    public static TObserver UniqueLog(this string log, float duration = 1f)
    {
        if (uniLogger.Validate() && uniLogger.name == log)
        {
            return null;
        }
        else
        {
            uniLogger = new TObserver()
            {
                name = log,
                duration = duration,
            }.Subscribe();
            Debug.Log(log);
            return uniLogger;
        }

    }
    public static void DataClone(this TObserver observer, Vector3 position)
    {
        //也就是说, 这个无参数的生命周期tick就是只能串行的, 
        // 必须像之前的order + Data形式才能实现变tick
        // 但是在Tick中会面临严重的类型转换开销
        // 我决定删除unique
        var cloneO = observer.Clone();
        cloneO.tick = () =>
        {
            return;
        };


    }

    public static TObserver DoTween(this Transform transform, Vector3 p1, Vector3 p2, float duration = 0.2f)
    {
        var ob = new TObserver()
        {
            name = $"TweenTransform : {transform}",
            end = () => transform.position = p2,
            duration = duration,
            tickType = 1
        };
        //但凡observer的函数中用到了自己的闭包,就必须保证observer是唯一的
        ob.tick = () => transform.position = Vector3.Lerp(p1, p2, ob.ToLinerLerp);
        return ob.Subscribe();
    }

    public static TObserver DoTween(this Transform transform, Vector3 p2, float duration = 0.2f) => transform.DoTween(transform.position, p2, duration);

}

